// vm-runner.ts
import * as vm from "vm";
import { Url } from "$/entity";
import { useRequestText } from "~/lib/http";

const createInjectedAPI = (url: Url) => {
  return {
    console: {
      log: console.log,
      info: console.info,
      warn: console.warn,
      error: console.error,
      debug: console.debug,
      trace: console.trace
    },
    es: {
      query: async (index: string, dsl: any) => {
        return useRequestText(`/${index}/_search`, {
          method: "POST",
          baseURL: url.value,
          data: dsl
          // TODO: 认证信息
        });
      },
      insert: async (index: string, data: any) => {
        return useRequestText(`/${index}/_doc`, {
          method: "POST",
          baseURL: url.value,
          data
          // TODO: 认证信息
        });
      },
      update: async (index: string, id: string, dsl: any) => {
        return useRequestText(`/${index}/_update/${id}`, {
          method: "POST",
          baseURL: url.value,
          data: dsl
          // TODO: 认证信息
        });
      },
      delete: async (index: string, id: string) => {
        return useRequestText(`/${index}/_delete/${id}`, {
          method: "DELETE",
          baseURL: url.value
          // TODO: 认证信息
        });
      }
    }
  };
};

/**
 * 在隔离上下文中执行异步脚本
 * 仅允许 JavaScript 原生对象和注入的 API
 * 支持顶层 await
 *
 * @param url - 当前 URL
 * @param code - 要执行的异步脚本（支持顶层 await）
 * @param timeout - 脚本执行超时（毫秒），默认 5000ms
 * @returns Promise<unknown> 脚本执行结果
 *
 * @example
 * const result = await runInSandbox(
 *    {},
 *   `await myAPI.fetchData();`,
 *   { myAPI: { fetchData: async () => 'Hello' } }
 * );
 */
export async function runInSandbox<T = unknown>(
  url: Url,
  code: string,
  timeout: number = 5000
): Promise<T> {
  // 构建沙箱环境：只包含 JS 原生全局 + 注入的 API
  const sandbox: Record<string, any> = {
    // JavaScript 原生全局对象（可按需增减）
    setTimeout,
    clearTimeout,
    setInterval,
    clearInterval,
    setImmediate,
    clearImmediate,
    Promise,
    Object,
    Array,
    String,
    Number,
    Boolean,
    Date,
    RegExp,
    Error,
    JSON,
    Math,
    // 注入你提供的 API
    ...createInjectedAPI(url)
  };

  // 创建隔离上下文
  const context = vm.createContext(sandbox);

  // 将脚本包装成 async 函数，以支持顶层 await
  // 注意：不能使用箭头函数，因为某些语法（如 arguments）可能受影响
  const wrappedCode = `
    (async () => {
      ${code}
    })()
  `;

  // 编译脚本
  const script = new vm.Script(wrappedCode, {
    filename: "sandbox-script.js",
    lineOffset: 0,
    columnOffset: 0
    // displayErrors: true
  });

  // 执行脚本，返回 Promise
  const result = await script.runInContext(context, {
    timeout, // 超时（毫秒）
    displayErrors: true
  });

  return result as T;
}
